package net.javadog.chatgpt.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.javadog.chatgpt.dto.request.MessageRequest;
import net.javadog.chatgpt.dto.response.MessageResponse;
import net.javadog.chatgpt.entity.Message;
import net.javadog.chatgpt.mapper.MessageMapper;
import net.javadog.chatgpt.service.MessageService;
import net.javadog.chatgpt.shiro.util.SubjectUtil;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;

/**
 * @Description: 信息接口实现类
 * @Author: hdx
 * @Date: 2023/1/13 16:32
 * @Version: 1.0
 */
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {

    @Override
    public MessageResponse add(MessageRequest messageRequest) {
        Long userId = SubjectUtil.getUserId();
        Message message = new Message();
        BeanUtil.copyProperties(messageRequest, message);
        message.setFromUserId(userId);
        message.setToUserId(0L);
        message.setCreateTime(new Date());
        message.setCreateBy(userId);
        // 保存数据
        this.save(message);
        // 调用OpenAI
        String questionAnswer = this.handleAI(message);
        // 保存入库
        Message robotMessage = new Message();
        robotMessage.setFromUserId(0L);
        robotMessage.setToUserId(userId);
        robotMessage.setCreateTime(new Date());
        robotMessage.setCreateBy(0L);
        robotMessage.setMsgContent(questionAnswer);
        this.save(robotMessage);
        MessageResponse messageResponse = new MessageResponse();
        BeanUtil.copyProperties(robotMessage, messageResponse);
        return messageResponse;
    }

    @Override
    public IPage<MessageResponse> page(MessageRequest messageRequest, Integer current, Integer size) {
        Long userId = SubjectUtil.getUserId();
        IPage<Message> page = new Page<>(current, size);
        LambdaQueryWrapper<Message> query = new LambdaQueryWrapper<>();
        query.eq(Message::getFromUserId, userId).eq(Message::getToUserId, 0L);
        query.or().eq(Message::getFromUserId, 0).eq(Message::getToUserId, userId);
        query.orderByDesc(Message::getCreateTime);
        IPage<Message> message = this.page(page, query);
        // IPage<entity>->IPage<vo>
        IPage<MessageResponse> convert = message.convert(FriendMsg -> BeanUtil.copyProperties(FriendMsg, MessageResponse.class));
        return convert;
    }

    private String handleAI(Message message){

        Generation gen = new Generation();

        com.alibaba.dashscope.common.Message systemMsg = com.alibaba.dashscope.common.Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("中文回复")
                .build();

        com.alibaba.dashscope.common.Message userMsg = com.alibaba.dashscope.common.Message.builder()
                .role(Role.USER.getValue())
                .content(message.getMsgContent())
                .build();

        GenerationParam param = GenerationParam.builder()
                .model("qwen-turbo")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .topK(50)
                .temperature(0.8f)
                .topP(0.8)
                .seed(1234)
                .build();

        try {
            return gen.call(param).getOutput().getChoices().get(0).getMessage().getContent();
        } catch (NoApiKeyException e) {
            throw new RuntimeException(e);
        } catch (InputRequiredException e) {
            throw new RuntimeException(e);
        }

    }
}
